<?php

namespace app\common\service;

use app\common\model\Consulting;
use app\common\model\ConsultingRedPacket;
use app\common\model\ConsultingReward;
use app\common\model\ConsultingServer;
use app\common\model\ConsultingSubsidy;
use app\common\model\LawCase;
use app\common\model\Member;
use app\common\model\MemberInvite;
use app\common\model\Trade;
use think\facade\Config;
use think\facade\Log;

/**
 * 分账服务
 * Class SettleConsultingServer
 * @package app\common\service
 */
class SettleConsultingServer
{

    /**
     * 结算 订单
     * @param int $id
     * @return bool
     */
    public function settleTrade($id): bool
    {
        $trade = Trade::where('id', $id)->find();

        // 支付状态
        if ($trade->payStatus != Trade::PAID) {
            Log::warning('订单结算：该订单未付款，不能结算' . $trade->id);
            return true;
        }

        // 退款状态
        if ($trade->refundStatus == Trade::REFUNDING) {
            Log::warning('订单结算：该订单正在退款，不能结算' . $trade->id);
            return false;
        }
        if ($trade->refundStatus == Trade::REFUNDED) {
            Log::warning('订单结算：该订单已退款，不能结算' . $trade->id);
            return true;
        }

        // 结算状态
        //  NOTSETTLE 不需要结算 UNSETTLED 待结算 SETTLING 结算中 SETTLED 已结算
        if ($trade->settleStatus != Trade::UNSETTLED) {
            Log::warning('订单结算：该订单不处于待结算状态' . $trade->id);
            if ($trade->settleStatus == Trade::NOTSETTLE || $trade->settleStatus == Trade::SETTLED) {
                return true;
            }
            return false;
        }

        // 结算中状态
        $trade->settleStatus = Trade::SETTLING;
        $trade->save();

        $this->settleTrade0($trade);

        // 已结算状态
        $trade->settleStatus = Trade::SETTLED;
        $trade->settleTime = time();
        $trade->save();

        return true;
    }

    /**
     * 结算 补贴
     * @param int $id
     * @return bool
     */
    public function settleSubsidy($id): bool
    {
        $consultingSubsidy = ConsultingSubsidy::where('id', $id)->find();

        // 结算状态 NOTSETTLE 不需要结算 UNSETTLED 待结算 SETTLING 结算中 SETTLED 已结算
        if ($consultingSubsidy->settleStatus != 'UNSETTLED') {
            Log::warning('补贴结算：该补贴不处于待结算状态' . $consultingSubsidy->id);
            if ($consultingSubsidy->settleStatus == 'NOTSETTLE' || $consultingSubsidy->settleStatus == 'SETTLED') {
                return true;
            }
            return false;
        }

        $consultingSubsidy->settleStatus = 'SETTLING';
        $consultingSubsidy->save();

        $subsidy = $consultingSubsidy->subsidy;
        if ($subsidy > 0) {
            // 分钱给律师

            // 获取被补贴的咨询
            $questionId = $consultingSubsidy->questionId;

            if (!is_id($questionId)) {
                $consultingId = $consultingSubsidy->consultingId;
                $consulting = Consulting::where('id', $consultingId)->find();
                if (!$consulting) {
                    Log::warning('补贴结算：问题和咨询都不存在或被删除 questionId =' . $questionId . ' consultingId=' . $consultingId);
                    return true;
                }
                $questionId = $consulting->questionId;
            }

            if (!is_id($questionId)) {
                Log::warning('补贴结算：问题ID不正确 questionId =' . $questionId);
                return true;
            }

            $consulting = $this->compareConsulting($questionId);

            if (!$consulting) {
                Log::warning('补贴结算：结算的咨询不存在或被删除');
                return false;
            }

            if (!is_id($consulting->lawyerId)) {
                $consultingSubsidy->settleStatus = 'NOTSETTLE';
                $consultingSubsidy->save();
                return true;
            }

            $lawyerId = $consulting->lawyerId;
            $lawyerShareMoney = $subsidy;

            $transferType = TRANSFER_SHARE_SUBSIDY;
            $payMethod = PAYMENT_ACCOUNT;
            $describe = '免费咨询补贴-律师佣金';
            $append = [
                'subsidyId' => $consultingSubsidy->id,
                'consultingId' => $consultingSubsidy->consultingId,
                'serverId' => $consultingSubsidy->serverId,
            ];
            $this->getTransfersServer()->pushTransferToMember($transferType, $lawyerId, $payMethod, $lawyerId, $lawyerShareMoney, $describe, $append);

            if (!is_id($consultingSubsidy->lawyerId)) {
                $consultingSubsidy->lawyerId = $lawyerId;
            }
            $consultingSubsidy->settleStatus = 'SETTLED';
            $consultingSubsidy->settleTime = time();
            $consultingSubsidy->settleConsultingId = $consulting->id;
            $consultingSubsidy->settleLawyerId = $lawyerId;
            $consultingSubsidy->settleLawyerMoney = $lawyerShareMoney;
            $consultingSubsidy->save();

            return true;
        } else {

            $consultingSubsidy->settleStatus = 'SETTLED';
            $consultingSubsidy->settleTime = time();
            $consultingSubsidy->save();

            return true;
        }
    }

    /**
     * @param Trade $trade
     * @return void
     */
    private function settleTrade0(Trade $trade): void
    {
        $tradeType = $trade->tradeType;
        if ($tradeType == TRADE_TOKEN_RECHARGE) {
            // 通信币 & 获客卡充值
            $this->settleTokenRecharge($trade);
        } elseif ($tradeType == TRADE_LAS_CASE) {
            // V1.0案源
            $this->settleTradeLawCase($trade);
        } elseif ($tradeType == TRADE_REWARD) {
            // 悬赏
            $this->settleReward($trade);
        } else {
            // 其他订单
            $this->settleTradeOther($trade);
        }
    }

    /**
     * 结算通信币 & 获客卡充值订单
     * @param Trade $trade
     * @return void
     */
    private function settleTokenRecharge(Trade $trade): void
    {
        $inviterShareRate = Config::get('profitsharing.tokenRecharge.inviterShareRate', 0);

        // 尝试获取邀请人
        $inviterId = MemberInvite::where('memberIdInvite', $trade->memberId)->value('memberId');

        // 分钱
        $this->shareTradeMoneyToInviter($trade, $inviterId, $inviterShareRate);
    }

    /**
     * 结算案源订单
     * @param Trade $trade
     * @return void
     */
    private function settleTradeLawCase(Trade $trade): void
    {
        $money = $trade->payMoney;

        // 查询到案源，查询案源提交人
        $lawCase = LawCase::where('id', $trade->lawCaseId)->find();
        if (!$lawCase) {
            Log::warning('案源订单结算：案源不存在或已被删除');
            return;
        }

        $creatorId = $lawCase->creatorId;
        $creatorShareRate = $lawCase->creatorShareRate;

        // 案源提交人
        $creatorShareMoney = 0;
        if (is_id($creatorId) && $creatorShareRate > 0) {
            $creatorShareMoney = round($money * $creatorShareRate, 2);

            if ($creatorShareMoney > 0) {

                // 转账
                $transferType = TRANSFER_SHARE_LAW_CASE;
                $payMethod = PAYMENT_ACCOUNT;
                $describe = '订单分账-案源分成';
                $append = [
                    'tradeId' => $trade->id,
                    'lawCaseId' => $lawCase->id,
                    // 'subsidyId' => '0',
                    // 'serverId' => $trade->serverId,
                    // 'redPacketId' => $trade->redPacketId,
                    // 'rewardId' => $trade->rewardId,
                ];
                $this->getTransfersServer()->pushTransferToMember($transferType, $creatorId, $payMethod, $creatorId, $creatorShareMoney, $describe, $append);

            }
        }

        // 保存分钱结果
        $trade->settleLawCaseMemberId = $creatorId;
        $trade->settleLawCaseMoney = $creatorShareMoney;
        $trade->save();

    }

    /**
     * 结算悬赏订单
     * @param Trade $trade
     * @return void
     */
    private function settleReward(Trade $trade): void
    {
        $questionId = $trade->questionId;

        if (!is_id($questionId)) {
            $consultingId = $trade->consultingId;
            $consulting = Consulting::where('id', $consultingId)->find();
            if (!$consulting) {
                Log::warning('悬赏订单结算：问题和咨询都不存在或被删除 questionId =' . $questionId . ' consultingId=' . $consultingId);
                return;
            }
            $questionId = $consulting->questionId;
        }

        if (!is_id($questionId)) {
            Log::warning('悬赏订单结算：问题ID不正确 questionId =' . $questionId);
            return;
        }

        $consulting = $this->compareConsulting($questionId);

        if (!$consulting) {
            Log::warning('悬赏订单结算：结算的咨询不存在或被删除');
            return;
        }

        // 悬赏
        $reward = ConsultingReward::where('id', $trade->rewardId)->find();
        if (!$reward) {
            Log::warning('悬赏订单结算：悬赏被删除或不存在');
            return;
        }

        $lawyerShareRate = $reward->lawyerShareRate;
        $inviterShareRate = $reward->inviterShareRate;

        // 尝试获取律师
        $lawyerId = $consulting->lawyerId;

        // 尝试获取邀请人
        $inviterId = MemberInvite::where('memberIdInvite', $trade->memberId)->value('memberId');

        // 分钱
        $this->shareTradeMoneyModel0($trade, $consulting, $lawyerId, $lawyerShareRate, $inviterId, $inviterShareRate);
    }

    /**
     * 结算律师需要分成的订单
     * @param Trade $trade
     * @return void
     */
    private function settleTradeOther(Trade $trade): void
    {
        $consultingId = $trade->consultingId;

        $consulting = Consulting::where('id', $consultingId)->find();
        if (!$consulting) {
            Log::warning('订单结算：咨询不存在或被删除 consultingId=' . $consultingId);
            return;
        }

        // 尝试获取律师
        $lawyerId = $consulting->lawyerId;
        $svip = 0;

        $lawyer = Member::where('id', $consulting->lawyerId)->find();
        if ($lawyer) {
            // 判断律师是不是SVIP，如果是SVIP,那么不给律师结算
            $svip = $lawyer->svip;
        }

        // 尝试获取邀请人
        $inviterId = MemberInvite::where('memberIdInvite', $trade->memberId)->value('memberId');

        // 律师分成金额（以订单预估金额分成）
        $lawyerShareMoney = $trade->lawyerMoney;

        // SVIP不分成
        if ($svip == 1) {
            $lawyerShareMoney = 0;
        }

        // 邀请人分成比例
        $inviterShareRate = 0;

        //确定订单类型,计算各方分成金额
        $tradeType = $trade->tradeType;
        if ($tradeType == TRADE_RED_PACKET) {
            // 红包
            $redPacket = ConsultingRedPacket::where('id', $trade->redPacketId)->find();
            if (!$redPacket) {
                Log::warning('订单结算：红包被删除或不存在 redPacketId=' . $trade->redPacketId);
                return;
            }
            $inviterShareRate = $redPacket->inviterShareRate;
        } elseif ($tradeType == TRADE_CONSULTING_SERVER || $tradeType == TRADE_LAWSUIT || $tradeType == TRADE_LANDING) {
            // 咨询服务 && 打官司 && h5落地页订单
            $server = ConsultingServer::where('id', $trade->serverId)->find();
            if (!$server) {
                Log::warning('订单结算：服务被删除或不存在 serverId=' . $trade->serverId);
                return;
            }
            $inviterShareRate = $server->inviterShareRate;
        } else {
            Log::warning('订单结算：不能结算该类型订单 tradeType=' . $tradeType);
            return;
        }

        // 分钱
        $this->shareTradeMoneyModel1($trade, $consulting, $lawyerId, $lawyerShareMoney, $inviterId, $inviterShareRate);

    }

    /**
     * 分钱（律师百分比分成）
     * @param Trade $trade
     * @param Consulting $consulting
     * @param $lawyerId
     * @param $lawyerShareRate
     * @param $inviterId
     * @param $inviterShareRate
     * @return void
     */
    private function shareTradeMoneyModel0(Trade $trade, Consulting $consulting, $lawyerId, $lawyerShareRate, $inviterId, $inviterShareRate)
    {

        // 用户总付款金额
        $money = $trade->payMoney;

        // 律师
        $lawyerShareMoney = 0;
        if (is_id($lawyerId) && $lawyerShareRate > 0) {
            $lawyerShareMoney = round($money * $lawyerShareRate, 2);
            if ($lawyerShareMoney > 0) {

                $transferType = TRANSFER_SHARE_LAWYER;
                $payMethod = PAYMENT_ACCOUNT;
                $describe = '订单分账-律师佣金分成';
                $append = [
                    'tradeId' => $trade->id,
                    'consultingId' => $consulting->id,
                    // 'subsidyId' => '0',
                    'serverId' => $trade->serverId,
                    'serverSkuId' => $trade->serverSkuId,
                    'redPacketId' => $trade->redPacketId,
                    'rewardId' => $trade->rewardId,
                    'lawsuitId' => $trade->lawsuitId,
                    'landingId' => $trade->landingId,
                    'landingType' => $trade->landingType,
                ];
                $this->getTransfersServer()->pushTransferToMember($transferType, $lawyerId, $payMethod, $lawyerId, $lawyerShareMoney, $describe, $append);
            }
        }

        // 邀请人
        $inviterShareMoney = 0;
        if (is_id($inviterId) && $inviterShareRate > 0) {
            $inviterShareMoney = round($money * $inviterShareRate, 2);
            if ($inviterShareMoney > 0) {

                $transferType = TRANSFER_SHARE_INVITER;
                $payMethod = PAYMENT_ACCOUNT;
                $describe = '订单分账-邀请人分成';
                $append = [
                    'tradeId' => $trade->id,
                    'consultingId' => $consulting->id,
                    // 'subsidyId' => '0',
                    'serverId' => $trade->serverId,
                    'serverSkuId' => $trade->serverSkuId,
                    'redPacketId' => $trade->redPacketId,
                    'rewardId' => $trade->rewardId,
                    'lawsuitId' => $trade->lawsuitId,
                    'landingId' => $trade->landingId,
                    'landingType' => $trade->landingType,
                ];
                $this->getTransfersServer()->pushTransferToMember($transferType, $inviterId, $payMethod, $inviterId, $inviterShareMoney, $describe, $append);
            }
        }

        // 保存分钱结果
        $trade->settleConsultingId = $consulting->id;
        $trade->settleLawyerId = $lawyerId;
        $trade->settleLawyerMoney = $lawyerShareMoney;
        $trade->settleInviterId = $inviterId;
        $trade->settleInviterMoney = $inviterShareMoney;
        $trade->save();
    }

    /**
     * 分钱（律师固定金额分成）
     * @param Trade $trade
     * @param Consulting $consulting
     * @param $lawyerId
     * @param $lawyerShareMoney
     * @param $inviterId
     * @param $inviterShareRate
     * @return void
     */
    private function shareTradeMoneyModel1(Trade $trade, Consulting $consulting, $lawyerId, $lawyerShareMoney, $inviterId, $inviterShareRate)
    {

        // 用户总付款金额
        $money = $trade->payMoney;

        // 律师
        if (is_id($lawyerId) && $lawyerShareMoney > 0) {
            $lawyerShareMoney = round($lawyerShareMoney, 2);
            if ($lawyerShareMoney > 0) {

                $transferType = TRANSFER_SHARE_LAWYER;
                $payMethod = PAYMENT_ACCOUNT;
                $describe = '订单分账-律师佣金分成';
                $append = [
                    'tradeId' => $trade->id,
                    'consultingId' => $consulting->id,
                    // 'subsidyId' => '0',
                    'serverId' => $trade->serverId,
                    'serverSkuId' => $trade->serverSkuId,
                    'redPacketId' => $trade->redPacketId,
                    'rewardId' => $trade->rewardId,
                    'lawsuitId' => $trade->lawsuitId,
                    'landingId' => $trade->landingId,
                    'landingType' => $trade->landingType,
                ];
                $this->getTransfersServer()->pushTransferToMember($transferType, $lawyerId, $payMethod, $lawyerId, $lawyerShareMoney, $describe, $append);
            }
        }

        // 邀请人
        $inviterShareMoney = 0;
        if (is_id($inviterId) && $inviterShareRate > 0) {
            $inviterShareMoney = round($money * $inviterShareRate, 2);
            if ($inviterShareMoney > 0) {

                $transferType = TRANSFER_SHARE_INVITER;
                $payMethod = PAYMENT_ACCOUNT;
                $describe = '订单分账-邀请人分成';
                $append = [
                    'tradeId' => $trade->id,
                    'consultingId' => $consulting->id,
                    // 'subsidyId' => '0',
                    'serverId' => $trade->serverId,
                    'serverSkuId' => $trade->serverSkuId,
                    'redPacketId' => $trade->redPacketId,
                    'rewardId' => $trade->rewardId,
                    'lawsuitId' => $trade->lawsuitId,
                    'landingId' => $trade->landingId,
                    'landingType' => $trade->landingType,
                ];
                $this->getTransfersServer()->pushTransferToMember($transferType, $inviterId, $payMethod, $inviterId, $inviterShareMoney, $describe, $append);
            }
        }

        // 保存分钱结果
        $trade->settleConsultingId = $consulting->id;
        $trade->settleLawyerId = $lawyerId;
        $trade->settleLawyerMoney = $lawyerShareMoney;
        $trade->settleInviterId = $inviterId;
        $trade->settleInviterMoney = $inviterShareMoney;
        $trade->save();
    }

    /**
     * 分钱给邀请人
     * @param Trade $trade
     * @param $inviterId
     * @param $inviterShareRate
     * @return void
     */
    private function shareTradeMoneyToInviter(Trade $trade, $inviterId, $inviterShareRate)
    {

        // 用户总付款金额
        $money = $trade->payMoney;

        // 邀请人
        $inviterShareMoney = 0;
        if (is_id($inviterId) && $inviterShareRate > 0) {
            $inviterShareMoney = round($money * $inviterShareRate, 2);
            if ($inviterShareMoney > 0) {

                $transferType = TRANSFER_SHARE_INVITER;
                $payMethod = PAYMENT_ACCOUNT;
                $describe = '订单分账-邀请人分成';
                $append = [
                    'tradeId' => $trade->id,
                    // 'consultingId' => $consulting->id,
                    // 'subsidyId' => '0',
                    'serverId' => $trade->serverId,
                    'serverSkuId' => $trade->serverSkuId,
                    'redPacketId' => $trade->redPacketId,
                    'rewardId' => $trade->rewardId,
                    'lawsuitId' => $trade->lawsuitId,
                    'landingId' => $trade->landingId,
                    'landingType' => $trade->landingType,
                    'accountTokenPlanId' => $trade->accountTokenPlanId,
                ];
                $this->getTransfersServer()->pushTransferToMember($transferType, $inviterId, $payMethod, $inviterId, $inviterShareMoney, $describe, $append);
            }
        }

        // 保存分钱结果
        // $trade->settleConsultingId = $consulting->id;
        // $trade->settleLawyerId = $lawyerId;
        // $trade->settleLawyerMoney = $lawyerShareMoney;
        $trade->settleInviterId = $inviterId;
        $trade->settleInviterMoney = $inviterShareMoney;
        $trade->save();
    }

    /**
     * 比较某提问的全部咨询，获取回复最多的咨询获取悬赏和补贴
     * @param $questionId
     * @return Consulting|null
     */
    private function compareConsulting($questionId): ?Consulting
    {
        if (!is_id($questionId)) {
            return null;
        }

        // 获取律师回复数量最多的咨询
        return Consulting::where('questionId', $questionId)
            ->whereIn('initMatchType', [0, 1, 2])
            ->where('lawyerId', '<>', '0')
            ->withCount([
                'lawyerMessages' => fn($query) => $query->where('senderType', 'member')->where('senderMemberType', '1'),
            ])
            ->select()
            ->order('lawyer_messages_count', 'DESC')
            ->values()
            ->first();
    }

    private function getTransfersServer(): TransfersServer
    {
        return app(TransfersServer::class);
    }

}